/**
 * Data Transfer Utilities for Multi-Page Architecture
 * Handles session management, URL parameters, and local storage
 */

/**
 * Session data transfer using sessionStorage
 */
export class DataTransfer {
    static SESSION_KEY = 'chatSession';
    static PREFERENCES_KEY = 'userPreferences';
    static SESSION_TIMEOUT = 24 * 60 * 60 * 1000; // 24 hours

    /**
     * Store session data
     * @param {Object} data Session data to store
     */
    static setSession(data) {
        try {
            const sessionData = {
                ...data,
                timestamp: Date.now()
            };
            sessionStorage.setItem(this.SESSION_KEY, JSON.stringify(sessionData));
            console.log('Session data stored:', sessionData);
        } catch (error) {
            console.error('Failed to store session data:', error);
            throw new Error('Session storage failed');
        }
    }

    /**
     * Get session data
     * @returns {Object|null} Session data or null if expired/missing
     */
    static getSession() {
        try {
            const data = sessionStorage.getItem(this.SESSION_KEY);
            if (!data) return null;

            const session = JSON.parse(data);
            
            // Check if session is expired
            if (Date.now() - session.timestamp > this.SESSION_TIMEOUT) {
                this.clearSession();
                return null;
            }

            return session;
        } catch (error) {
            console.error('Failed to retrieve session data:', error);
            this.clearSession();
            return null;
        }
    }

    /**
     * Clear session data
     */
    static clearSession() {
        try {
            sessionStorage.removeItem(this.SESSION_KEY);
            console.log('Session data cleared');
        } catch (error) {
            console.error('Failed to clear session data:', error);
        }
    }

    /**
     * Update session data
     * @param {Object} updates Partial updates to apply to session
     */
    static updateSession(updates) {
        const currentSession = this.getSession();
        if (currentSession) {
            this.setSession({ ...currentSession, ...updates });
        } else {
            throw new Error('No active session to update');
        }
    }

    /**
     * Store user preferences
     * @param {Object} prefs User preferences
     */
    static setPreferences(prefs) {
        try {
            localStorage.setItem(this.PREFERENCES_KEY, JSON.stringify(prefs));
        } catch (error) {
            console.error('Failed to store preferences:', error);
        }
    }

    /**
     * Get user preferences
     * @returns {Object} User preferences
     */
    static getPreferences() {
        try {
            const data = localStorage.getItem(this.PREFERENCES_KEY);
            return data ? JSON.parse(data) : {};
        } catch (error) {
            console.error('Failed to retrieve preferences:', error);
            return {};
        }
    }

    /**
     * Check if session storage is available
     * @returns {boolean} True if available
     */
    static isStorageAvailable() {
        try {
            const test = '__storage_test__';
            sessionStorage.setItem(test, test);
            sessionStorage.removeItem(test);
            return true;
        } catch (error) {
            return false;
        }
    }
}

/**
 * URL parameter utilities
 */
export class URLUtils {
    /**
     * Get all URL parameters as object
     * @returns {Object} URL parameters
     */
    static getParams() {
        try {
            const params = new URLSearchParams(window.location.search);
            const result = {};
            for (const [key, value] of params) {
                result[key] = decodeURIComponent(value);
            }
            return result;
        } catch (error) {
            console.error('Failed to parse URL parameters:', error);
            return {};
        }
    }

    /**
     * Get specific URL parameter
     * @param {string} name Parameter name
     * @param {string} defaultValue Default value if parameter not found
     * @returns {string} Parameter value
     */
    static getParam(name, defaultValue = null) {
        const params = this.getParams();
        return params[name] || defaultValue;
    }

    /**
     * Build URL with parameters
     * @param {string} base Base URL
     * @param {Object} params Parameters to append
     * @returns {string} Complete URL
     */
    static buildURL(base, params = {}) {
        try {
            const url = new URL(base, window.location.origin);
            Object.entries(params).forEach(([key, value]) => {
                if (value !== null && value !== undefined && value !== '') {
                    url.searchParams.set(key, encodeURIComponent(value));
                }
            });
            return url.toString();
        } catch (error) {
            console.error('Failed to build URL:', error);
            return base;
        }
    }

    /**
     * Navigate to URL with parameters
     * @param {string} path Target path
     * @param {Object} params Parameters to include
     */
    static navigateTo(path, params = {}) {
        const url = this.buildURL(path, params);
        window.location.href = url;
    }

    /**
     * Replace current URL with new parameters
     * @param {Object} params Parameters to set
     */
    static updateParams(params = {}) {
        const url = this.buildURL(window.location.pathname, params);
        window.history.replaceState({}, '', url);
    }

    /**
     * Check if current URL has specific parameter
     * @param {string} name Parameter name
     * @returns {boolean} True if parameter exists
     */
    static hasParam(name) {
        return new URLSearchParams(window.location.search).has(name);
    }

    /**
     * Remove parameters from URL
     * @param {string[]} paramNames Parameters to remove
     */
    static removeParams(paramNames = []) {
        const params = new URLSearchParams(window.location.search);
        paramNames.forEach(name => params.delete(name));
        
        const newURL = `${window.location.pathname}${params.toString() ? '?' + params.toString() : ''}`;
        window.history.replaceState({}, '', newURL);
    }
}

/**
 * Navigation utilities for multi-page application
 */
export class NavigationUtils {
    /**
     * Navigate to homepage
     * @param {Object} params Optional URL parameters
     */
    static goHome(params = {}) {
        URLUtils.navigateTo('/', params);
    }

    /**
     * Navigate to chat room
     * @param {string} roomId Room ID
     * @param {Object} additionalParams Additional parameters
     */
    static goToRoom(roomId, additionalParams = {}) {
        const params = {
            roomId,
            ...additionalParams
        };
        URLUtils.navigateTo('/room.html', params);
    }

    /**
     * Navigate to homepage with invite code
     * @param {string} inviteCode Invite code
     */
    static goToInvite(inviteCode) {
        URLUtils.navigateTo('/', { invite: inviteCode });
    }

    /**
     * Prepare room navigation with session data
     * @param {Object} roomData Room creation/join response
     */
    static prepareRoomNavigation(roomData) {
        // Store session data
        DataTransfer.setSession({
            userId: roomData.userId,
            roomId: roomData.roomId,
            nickname: roomData.nickname || roomData.user?.nickname,
            sessionToken: roomData.sessionToken,
            isOwner: roomData.isOwner || false
        });

        // Navigate to room
        this.goToRoom(roomData.roomId);
    }
}

/**
 * Error handling utilities for navigation
 */
export class ErrorHandler {
    /**
     * Handle session validation errors
     * @param {Error} error Error object
     * @param {string} redirectPath Where to redirect on error
     */
    static handleSessionError(error, redirectPath = '/') {
        console.error('Session validation error:', error);
        DataTransfer.clearSession();
        
        const params = {
            error: 'session_invalid',
            message: 'Your session has expired. Please join the room again.'
        };
        
        URLUtils.navigateTo(redirectPath, params);
    }

    /**
     * Handle room access errors
     * @param {Error} error Error object
     */
    static handleRoomError(error) {
        console.error('Room access error:', error);
        
        let message = 'Unable to access room.';
        if (error.message.includes('not found')) {
            message = 'Room not found or no longer available.';
        } else if (error.message.includes('full')) {
            message = 'Room is full. Please try again later.';
        }
        
        const params = {
            error: 'room_access',
            message
        };
        
        URLUtils.navigateTo('/', params);
    }

    /**
     * Display error message to user
     * @param {string} message Error message
     * @param {string} type Error type (error, warning, info)
     */
    static showError(message, type = 'error') {
        // This will be implemented by UI components
        const event = new CustomEvent('show-error', {
            detail: { message, type }
        });
        document.dispatchEvent(event);
    }
}

/**
 * Validation utilities
 */
export class ValidationUtils {
    /**
     * Validate room ID format
     * @param {string} roomId Room ID to validate
     * @returns {boolean} True if valid
     */
    static isValidRoomId(roomId) {
        return typeof roomId === 'string' && roomId.length >= 6 && /^[a-zA-Z0-9]+$/.test(roomId);
    }

    /**
     * Validate session data
     * @param {Object} session Session data
     * @returns {boolean} True if valid
     */
    static isValidSession(session) {
        return session &&
               session.userId &&
               session.roomId &&
               session.sessionToken &&
               this.isValidRoomId(session.roomId);
    }

    /**
     * Validate nickname
     * @param {string} nickname Nickname to validate
     * @returns {boolean} True if valid
     */
    static isValidNickname(nickname) {
        return typeof nickname === 'string' && 
               nickname.trim().length >= 1 && 
               nickname.trim().length <= 30;
    }
}